/** @file
* T3SDK输出函数
* @author  马进朝
* @author  恒生电子股份有限公司
* @version 1.0
* @date    20181205
* 20190416 yanz #135107 SenderId支持向指定位置设置、读取值
* 20190705 yanz #150613 新增接口用于设置全链路的spanid
* 20191028 huxb #161459 支持消息中心发布订阅
* 20191218 shizj #186107 t3sdk订阅发布支持设置gsvp
* 20200330 yanz #200119 提供删除域值的接口
*/

#ifndef _T3_T3SDK_H_
#define _T3_T3SDK_H_
#include <stdio.h>
#include <string.h>

///本项目命名空间定义
#define T3SDK_NAMESPACE		t3sdk
///define the namesapce
#define NAMESPACE_BEGIN(x)		namespace x {
#define NAMESPACE_END			}
#define USING_NAMESPACE(x)		using namespace x;

#define BEGIN_T3SDK_NAMESPACE	NAMESPACE_BEGIN(T3SDK_NAMESPACE)
#define END_T3SDK_NAMESPACE	NAMESPACE_END
#define USING_T3SDK_NAMESPACE	USING_NAMESPACE(T3SDK_NAMESPACE)

#ifdef _WIN32
#if !defined( FUNCTION_CALL_MODE )
#define FUNCTION_CALL_MODE		__stdcall
#endif
#else
#define FUNCTION_CALL_MODE
#endif
BEGIN_T3SDK_NAMESPACE

#define MAX_T3SDK_USER_TOKEN_LEN  1024
#define T3SDK_USER_TOKEN "user_token"

///20191028 huxb #161459 支持消息中心发布订阅
#define IDENTITY_NAME_LENGTH    32  /**< 发布者业务名字长度 */
#define MAX_IPADDRESS_LEN	    32  /**< IP地址长度 */
#define MAX_RAND_LEN	        4   /**< 随机数长度 */

/** 发布者名称长度 */
#define MAX_BIZNAME_LEN IDENTITY_NAME_LENGTH+1+MAX_IPADDRESS_LEN+1+MAX_RAND_LEN+2



//会话状态
#define CONNECT_DISCONNCT 0
#define CONNECT_CONNECTTING 1
#define CONNECT_CONNECTED 2

#define MAX_TOPICNAME_LEN 256


#define T3SDK_MAX_BRANCH_NO_LEN  256 
#define T3SDK_MAX_COMPANY_NO_LEN 256 
#define T3SDK_MAX_OSPF_LEN       256


struct IBase
{
	virtual ~IBase() {};

	virtual unsigned long  FUNCTION_CALL_MODE QueryInterface(const char *iid, IBase **ppv) = 0;

	virtual unsigned long  FUNCTION_CALL_MODE AddRef() = 0;

	virtual unsigned long  FUNCTION_CALL_MODE Release() = 0;
};

typedef struct tagNetSpeedReq
{
	int  iIndex;
	int  iPort;
	char szAddress[32];
	tagNetSpeedReq()
	{
		iIndex = 0;
		iPort = 0;
		szAddress[0] = '\0';
	}
}NetSpeedReq;

typedef struct tagNetSpeedAns
{
	NetSpeedReq SpeedReq;
	int         iErrNo;
	int         iConnCount;
	double      dNetDelay;
	double      dNetSpeed;
	tagNetSpeedAns()
	{
		iErrNo = 0;
		iConnCount = 0;
		dNetDelay = 0.0;
		dNetSpeed = 0.0;
	}
}NetSpeedAns;

///20191028 huxb #161459 支持消息中心发布订阅
/* 指定路由信息 */
typedef struct tagSubRouteInfo
{
	int iSystemNo;                       //系统号
	int iSubSystemNo;                    //子系统号
	char szBranchNo[T3SDK_MAX_BRANCH_NO_LEN + 1];       //分支号
	char szCompanyNo[T3SDK_MAX_COMPANY_NO_LEN + 1];        //公司编号
	char szOspfName[T3SDK_MAX_OSPF_LEN + 1];         //OSPF
	tagSubRouteInfo()
	{
		memset(this, 0, sizeof(tagSubRouteInfo));
	}
}SUB_ROUTER_INFO;

/**
* @brief 订阅回调接口返回的数据定义，除了订阅需要的业务体之外，还需要返回的数据
*/
typedef struct tagSubscribeRecvData
{
	const char * lpFilterData;		/**< 过滤字段的数据头指针，用解包器解包 */
	int iFilterDataLen;				/**< 过滤字段的数据长度 */
	const char * lpAppData;			/**< 附加数据的数据头指针 */
	int iAppDataLen;				/**< 附加数据的长度 */
	char szTopicName[MAX_TOPICNAME_LEN + 1];	/**< 主题名字 */
	char szSender[MAX_BIZNAME_LEN + 1];			/**< 发布者名称 */
	unsigned uMsgNo;				/**< 消息序号 */
	tagSubscribeRecvData()
	{
		memset(this, 0, sizeof(tagSubscribeRecvData));
	}
}SUBSCRIBE_RECVDATA, *LPSUBSCRIBE_RECVDATA;

//消息类型
enum MessageType
{
	HSRequest = 0,
	HSAnswer = 1
};
//业务体类型
enum BodyType
{
	HSPack = 0,
	HSJson = 1,
	HSRawData = 2
};
//业务体编码类型
enum BodyEncoding
{
	HSGBK = 0,
	HSUTF8 = 1
};
//业务体加密类型
enum BodyEncryptType
{
	HSNONE = 0,
	HSRSA = 1,
	HSSM2 = 2,
	HSAES = 3,
	HSSM4 = 4
};
//调试信息类型
enum DebugType
{
	HSNone = 0,
	HSTrace = 1,
	HSMethod = 2
};

/** 主题可靠等级 */
enum ReliableLevel
{
	LEVEL_DOBEST = 0,    /**< 尽力而为 */
	LEVEL_DOBEST_BYSEQ = 1,    /**< 尽力有序 */
	LEVEL_MEM = 2,    /**< 内存 */
	LEVEL_FILE = 3,    /**< 文件 */
	LEVEL_SYSTEM = 4     /**< 系统 */
};

///20191028 huxb #161459 支持消息中心发布订阅
struct IT3JsonStr : public IBase
{
	virtual ~IT3JsonStr() {};
	/**
	* 设置JSON串
	* @param szJsonStr JSON串
	* @param uLen JSON串长度
	* @param bCopy 是否拷贝内存
	* @return 0表示成功，其他表示失败
	*/
	virtual int FUNCTION_CALL_MODE SetJsonStr(const char * szJsonStr, unsigned uLen, bool bCopy = false) = 0;
	/**
	* 获取JSON串
	* @param uLen 返回JSON串长度
	* @return JSON串
	*/
	virtual const char * FUNCTION_CALL_MODE GetJsonStr(unsigned &uLen) = 0;
	/**
	* 重置数据
	*/
	virtual void FUNCTION_CALL_MODE Reset() = 0;
};

struct IT3Message : public IBase
{
	virtual ~IT3Message() {};
	/**
	* 设置功能号，不可为空
	* @param szFunction功能号字符串
	*/
	virtual void FUNCTION_CALL_MODE SetFunction(const char* szFunction) = 0;
	/**
	* 获取功能号
	* @return功能号字符串
	*/
	virtual const char * FUNCTION_CALL_MODE GetFunction() = 0;
	/**
	* 设置包类型，不可为空
	* @param type
	*/
	virtual void FUNCTION_CALL_MODE SetMessageType(MessageType type = HSRequest) = 0;
	/**
	* 获取包类型
	* @return 包类型
	*/
	virtual MessageType FUNCTION_CALL_MODE GetMessageType() = 0;
	/**
	* 设置ShardingInfo
	* @param szShardingInfo
	*/
	virtual void FUNCTION_CALL_MODE SetShardingInfo(const char* szShardingInfo) = 0;
	/**
	* 获取ShardingInfo
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetShardingInfo() = 0;
	/**
	* 设置业务体内容，不为空
	* @param lpContent 业务体二进制指针
	* @param iLen 业务体二进制长度
	*/
	virtual void FUNCTION_CALL_MODE SetBody(void* lpContent, int iLen, BodyType bodyType = HSJson, BodyEncoding encodingType = HSUTF8, BodyEncryptType encryType = HSNONE) = 0;
	/**
	* 获取业务体内容
	* @param iLen 业务体二进制长度，出参
	* @return 二进制指针
	*/
	virtual const void* FUNCTION_CALL_MODE GetBody(int& iLen) = 0;
	/**
	* 设置业务内容类型，是配合SetBody使用
	* @param type
	*/
	virtual void FUNCTION_CALL_MODE SetBodyType(BodyType type = HSJson) = 0;
	/**
	* 获取业务内容类型
	* @return 业务体格式类型
	*/
	virtual BodyType FUNCTION_CALL_MODE GetBodyType() = 0;
	/**
	* 设置业务内容编码类型，是配合SetBody使用
	* @param type
	*/
	virtual void FUNCTION_CALL_MODE SetBodyEncoding(BodyEncoding type = HSUTF8) = 0;
	/**
	* 获取业务内容编码类型
	* @return 业务体编码类型
	*/
	virtual BodyEncoding FUNCTION_CALL_MODE GetBodyEncoding() = 0;
	/**
	* 设置业务内容加密类型，是配合SetBody使用
	* @param type
	*/
	virtual void FUNCTION_CALL_MODE SetBodyEncryptType(BodyEncryptType type = HSNONE) = 0;
	/**
	* 获取业务内容加密类型
	* @return 业务体加密类型
	*/
	virtual BodyEncryptType FUNCTION_CALL_MODE GetBodyEncryptType() = 0;
	/**
	* 设置group信息
	* @param szGroup
	*/
	virtual void FUNCTION_CALL_MODE SetGroup(const char* szGroup) = 0;
	/**
	* 获取group信息
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetGroup() = 0;
	/**
	* 设置service信息，不可为空
	* @param szService
	*/
	virtual void FUNCTION_CALL_MODE SetService(const char* szService) = 0;
	/**
	* 获取service信息
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetService() = 0;
	/**
	* 设置version
	* @param szVersion
	*/
	virtual void FUNCTION_CALL_MODE SetVersion(const char* szVersion) = 0;
	/**
	* 获取version信息
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetVersion() = 0;
	/**
	* 设置Security
	* @param szSecurity
	*/
	virtual void FUNCTION_CALL_MODE SetSecurity(const char* szSecurity) = 0;
	/**
	* 获取Security信息
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetSecurity() = 0;
	/**
	* 设置唯一标识traceID
	* @param type
	*/
	virtual void FUNCTION_CALL_MODE SetTraceID(const char* szTraceID) = 0;
	/**
	* 获取唯一标识
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetTraceID() = 0;
	/**
	* 设置调试类型
	* @param type
	*/
	virtual void FUNCTION_CALL_MODE SetDebugType(DebugType type) = 0;
	/**
	* 获取调试类型
	* @return
	*/
	virtual DebugType FUNCTION_CALL_MODE GetDebugType() = 0;
	/**
	* 设置发送者编号
	* @param nSenderId
	*/
	virtual void FUNCTION_CALL_MODE SetSenderId(const int nSenderId) = 0;
	/**
	* 获取发送者编号
	* @return
	*/
	virtual int FUNCTION_CALL_MODE GetSenderId() = 0;
	/**
	* 设置包序号
	* @param nPacketId
	*/
	virtual void FUNCTION_CALL_MODE SetPacketId(const int nPacketId) = 0;
	/**
	* 获取包序号
	* @return
	*/
	virtual int FUNCTION_CALL_MODE GetPacketId() = 0;
	/**
	* 设置错误号
	* @param nErrorNo
	*/
	virtual void FUNCTION_CALL_MODE SetErrorNo(const int nErrorNo) = 0;
	/**
	* 获取错误号
	* @return
	*/
	virtual int FUNCTION_CALL_MODE GetErrorNo() = 0;
	/**
	* 设置错误信息
	* @param nErrorNo
	*/
	virtual void FUNCTION_CALL_MODE SetErrorInfo(const char* szErrorInfo) = 0;
	/**
	* 获取错误信息
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetErrorInfo() = 0;
	/**
	* 设置返回码
	* @param nReturnCode
	*/
	virtual void FUNCTION_CALL_MODE SetReturnCode(const int nReturnCode) = 0;
	/**
	* 获取返回码
	* @return
	*/
	virtual int FUNCTION_CALL_MODE GetReturnCode() = 0;
	/**
	* 请求转应答
	* @return 0成功，否则失败
	*/
	virtual int	FUNCTION_CALL_MODE ChangeReq2AnsMessage() = 0;
	/**
	* 解析二进制
	* @param lpBuff 二进制指针
	* @param nBuffLen 二进制长度
	* @return 0成功，否则失败
	*/
	virtual int	FUNCTION_CALL_MODE SetBuff(const void* lpBuff, int nBuffLen) = 0;
	/**
	* 获取二进制
	* @param nBuffLen 二进制长度 出参
	* @return 二进制指针
	*/
	virtual void* FUNCTION_CALL_MODE GetBuff(int& nBuffLen) = 0;
	/**
	* 增加时间戳
	*/
	virtual void FUNCTION_CALL_MODE AddTimeStamp() = 0;
	/**
	* 清除消息内的字段，可以下次复用
	*/
	virtual void FUNCTION_CALL_MODE ReSet() = 0;

	//20190416 yanz #135107 SenderId支持向指定位置设置、读取值
	virtual void FUNCTION_CALL_MODE SetSenderIdEx(const int nSenderId, int index) = 0;
	
	virtual int FUNCTION_CALL_MODE GetSenderIdEx(int index) = 0;
	/**
	* 设置trace用户附加数据
	* @param szTraceUserInfo
	*/
	virtual void FUNCTION_CALL_MODE SetTraceUserInfo(const char* szTraceUserInfo) = 0;
	/**
	* 获取trace用户附加数据
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetTraceUserInfo() = 0;
	/**
	* 设置分片号信息
	* @param szPartition
	*/
	virtual void FUNCTION_CALL_MODE SetPartition(const char* szPartition) = 0;
	/**
	* 获取分片号信息
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetPartition() = 0;

	//20190705 yanz #150613 新增接口用于设置全链路的spanid
	/**
	* 设置消息跨度SpanID
	* @param szPartition
	*/
	virtual void FUNCTION_CALL_MODE SetSpanID(const char* szSpanID) = 0;
	/**
	* 获取消息跨度
	* @return
	*/
	virtual const char* FUNCTION_CALL_MODE GetSpanID() = 0;
	//20200330 yanz #200119 提供删除域值的接口
	/**
	* 删除发送者编号域值
	* @return
	*/
	virtual int FUNCTION_CALL_MODE RemoveSenderId() = 0;
	/**
	* 删除包序号域值
	* @return
	*/
	virtual int FUNCTION_CALL_MODE RemovePacketId() = 0;

};
///连接对象 IT3Connection 的参数配置对象
/**
* 包括从文件加载、保存到文件，读写操作
*/
class IT3Config : public IBase
{
public:
	virtual ~IT3Config() {};
	/**
	* 从文件加载
	* @param szFileName 文件名，格式类似ini，具体参考开发包示例
	* @return 返回0表示成功，否则失败
	*/
	virtual int FUNCTION_CALL_MODE Load(const char *szFileName) = 0;

	/**
	* 保存到文件
	* @param szFileName 文件名
	* @return 返回0表示成功，否则失败
	*/
	virtual int FUNCTION_CALL_MODE Save(const char *szFileName) = 0;

	/**
	* 取字符串值
	* @param szSection 节名
	* @param szEntry   变量名
	* @param szDefault 缺省值
	* @return 字符串值，没有找到时返回szDefault
	*/
	virtual const char * FUNCTION_CALL_MODE GetString(const char *szSection, const char *szEntry, const char *szDefault) = 0;

	/**
	* 取整数值
	* @param szSection 节名
	* @param szEntry   变量名
	* @param iDefault  缺省值
	* @return 整数值，没有找到时返回iDefault
	*/
	virtual int FUNCTION_CALL_MODE GetInt(const char *szSection, const char *szEntry, int iDefault) = 0;

	/**
	* 设置字符串值
	* @param szSection 节名
	* @param szEntry   变量名
	* @param szValue   值
	* @return 0表示成功，否则失败
	*/
	virtual int FUNCTION_CALL_MODE SetString(const char *szSection, const char *szEntry, const char *szValue) = 0;

	/**
	* 设置整数值
	* @param szSection 节名
	* @param szEntry   变量名
	* @param iValue    值
	* @return 0表示成功，否则失败
	*/
	virtual int FUNCTION_CALL_MODE SetInt(const char *szSection, const char *szEntry, int iValue) = 0;
};
class IT3Connection;

///20191028 huxb #161459 支持消息中心发布订阅
/**
* 消息中心过滤器接口
*/
class IT3Filter :public IBase
{
public:
	/**
	* 根据下标获取过滤条件名称
	* @param index 下标
	* @return 返回下标对应的过滤条件名称，非法下标返回NULL.
	*/
	virtual const char * FUNCTION_CALL_MODE GetFilterNameByIndex(int index) = 0;

	/**
	* 根据下标获取过滤条件值
	* @param index 下标
	* @return 返回下标对应的过滤条件值，非法下标返回NULL.
	*/
	virtual const char * FUNCTION_CALL_MODE GetFilterValueByIndex(int index) = 0;

	/**
	* 根据过滤条件名称获取值
	* @param fileName 过滤条件名称
	* @return 返回对应的过滤条件值，不存在返回NULL.
	*/
	virtual const char * FUNCTION_CALL_MODE GetFilterValue(const char *  fileName) = 0;

	/**
	* 获取过滤条件的个数
	* @return 返回对应过滤条件的个数，没有返回0
	*/
	virtual int FUNCTION_CALL_MODE GetCount() = 0;

	/**
	* 设置过滤条件
	* @param filterName 过滤条件名称
	* @param filterValue 过滤条件值
	*/
	virtual void FUNCTION_CALL_MODE SetFilter(const char * filterName, const char * filterValue) = 0;

	/**
	* 重置所有过滤条件，包括名称和值
	*/
	virtual void FUNCTION_CALL_MODE Reset() = 0;
};

/**
* 订阅参数类接口
*/
class IT3SubParam :public IBase
{
public:
	/**
	* 设置主题名字
	* @param szName 对应的主题名字
	*/
	virtual void FUNCTION_CALL_MODE  SetTopicName(const char * szName) = 0;

	/**
	* 设置附加数据
	* @param szAppData 附加数据
	*/
	virtual void FUNCTION_CALL_MODE  SetAppData(const char * szAppData) = 0;

	/**
	* 添加过滤条件
	* @param filterName 过滤条件的名字
	* @param filterValue 过滤条件的值
	*/
	virtual void FUNCTION_CALL_MODE  SetFilter(const char * filterName, const char * filterValue) = 0;

	/**
	* 设置是否补缺标志
	* @param bFromNow true表示需要之前的数据，也就是补缺，false表示不需要补缺
	*/
	virtual void FUNCTION_CALL_MODE  SetFromNow(bool bFromNow) = 0;

	/**
	* 获取主题名字
	* @return 返回主题名字信息
	*/
	virtual const char * FUNCTION_CALL_MODE  GetTopicName() = 0;

	/**
	* 获取附加数据
	* @return 返回附加数据，没有返回NULL
	*/
	virtual const char * FUNCTION_CALL_MODE  GetAppData() = 0;

	/**
	* 获取对应的过滤字段的名字
	* @param index 对应的过滤条件下标
	* @return 返回对应的下标过滤条件的名字，否则返回NULL.
	*/
	virtual const char * FUNCTION_CALL_MODE  GetFilterNameByIndex(int index) = 0;

	/**
	* 根据下标获取过滤条件的值
	* @param index 对应的过滤条件下标
	* @return 返回对应的下标过滤条件的值，否则返回NULL.
	*/
	virtual const char * FUNCTION_CALL_MODE  GetFilterValueByIndex(int index) = 0;

	/**
	* 根据过滤条件的名字获取过滤条件的值
	* @param fileName 对应的过滤条件名字
	* @return 返回对应的过滤条件名字的条件值，否则返回NULL.
	*/
	virtual const char * FUNCTION_CALL_MODE  GetFilterValue(const char *  fileName) = 0;

	/**
	* 获取过滤条件的个数
	* @return 返回对应过滤条件的个数，没有返回0
	*/
	virtual int   FUNCTION_CALL_MODE  GetFilterCount() = 0;

	/**
	* 获取是否补缺的标志
	* @return 返回对应的补缺标志
	*/
	virtual bool  FUNCTION_CALL_MODE  GetFromNow() = 0;

	/**
	* 设置是否更新消息序号
	* @param bUpdate true表示需要更新消息序号，false表示不更新
	*/
	virtual void FUNCTION_CALL_MODE  SetUpdateMsgNo(bool bUpdate) = 0;

	/**
	* 获取是否更新消息序号
	* @return 返回是否更新消息序号
	*/
	virtual bool  FUNCTION_CALL_MODE  GetUpdateMsgNo() = 0;

	//添加过滤条件
	/**
	* @param filterName 过滤条件的名字
	* @param iFileterValue 过滤条件的Int值
	**/
	virtual void FUNCTION_CALL_MODE SetFilterInt(const char * filterName, int filterValue) = 0;

	//根据过滤条件的名字获取过滤条件的Int值
	/**
	* @param filterName 对应的过滤条件名字
	* @return 返回对应的过滤条件名字的条件Int值，否则返回0。
	**/
	virtual int FUNCTION_CALL_MODE GetFilterIntValue(const char * filterName) = 0;

	//根据下标获取过滤条件的值
	/**
	* @param index 对应的过滤条件下标
	* @return 返回对应的下标过滤条件的值，否则返回0。
	**/
	virtual int FUNCTION_CALL_MODE GetFilterIntValueByIndex(int index) = 0;

	/**
	* 设置订阅名称
	* @param subinfoName 订阅项名称
	*/
	virtual void FUNCTION_CALL_MODE  SetSubInfoName(const char * subinfoName) = 0;

	/**
	* 获取订阅名称
	* @return 返回订阅名称
	*/
	virtual const char*  FUNCTION_CALL_MODE  GetSubInfoName() = 0;

	/**
	* 重置过滤条件
	*/
	virtual void FUNCTION_CALL_MODE  ResetFilter() = 0;
};

class IT3Subscriber;



/**
* 订阅回调接口，上层应用通过这个接口，接收主推过来的消息
*/
class IT3SubCallback : public IBase
{
public:

	/**
	* 收到发布消息的回调
	* @param lpSub 回调的订阅指针
	* @param subscribeIndex 消息对应的订阅标识，这个标识来自于SubscribeTopic函数的返回
	* @param lpData 返回消息的二进制指针，一般是消息的业务体打包内容
	* @param nLength 二进制数据的长度
	* @param lpRecvData 主推消息的其他字段返回，主要包含了附加数据，过滤信息，主题名字，详细参看前面结构体定义
	* @return 无
	*/
	virtual void FUNCTION_CALL_MODE OnReceived(IT3Subscriber *lpSub, int subscribeIndex, const void *lpData, int nLength, LPSUBSCRIBE_RECVDATA lpRecvData) = 0;

	/**
	* 收到剔除订阅项的消息回调，一般在拥有踢人策略的主题下会回调这个接口,这个回调里面不需要取消订阅，底层已经取消这个订阅，只是一个通知接口
	* @param lpSub 回调的订阅指针
	* @param subscribeIndex 消息对应的订阅标识，这个标识来自于SubscribeTopic函数的返回
	* @param TickMsgInfo 踢人的错误信息，主要是包含具体重复的订阅项位置信息
	* @return 无
	*/
	virtual void FUNCTION_CALL_MODE OnRecvTickMsg(IT3Subscriber *lpSub, int subscribeIndex, const char* TickMsgInfo) = 0;
};


/**
* 订阅接口的定义
*/
class IT3Subscriber : public IBase
{
public:

	/**
	* 订阅主题
	* @param lpSubscribeParamInter 上面定义的订阅参数结构
	* @param uiTimeout 超时时间
	* @param lpBizCheckInfo 业务权限校验信息（JSON串形式），需要调用者自己申请以及释放
	* @param lpBizCheckResult 业务权限校验结果（JSON串形式），需要调用者自己申请以及释放
	* @return 返回值大于0，表示当前订阅成功的订阅标识，外面要记住这个标识和订阅项之间的映射关系，这个标识需要用于取消订阅和接收消息的回调里面.
	*		  返回其他值，根据错误号获取错误信息.
	*/
	virtual int FUNCTION_CALL_MODE SubscribeTopic(IT3SubParam* lpSubscribeParamInter, unsigned int uiTimeout, IT3JsonStr * lpBizCheckInfo = NULL, IT3JsonStr * lpBizCheckResult = NULL) = 0;

	/**
	* 取消订阅主题
	* @param subscribeIndex 消息对应的订阅标识，这个标识来自于SubscribeTopic函数的返回
	* @return 返回0表示取消订阅成功，返回其他值，根据错误号获取错误信息.
	*/
	virtual int FUNCTION_CALL_MODE CancelSubscribeTopic(int subscribeIndex) = 0;


	/**
	* 取消订阅主题
	* @param topicName 主题名字
	* @param lpFilterInterface 对应的过滤条件
	* @return 返回0表示取消订阅成功，返回其他值，根据错误号获取错误信息.
	*/
	virtual int FUNCTION_CALL_MODE CancelSubscribeTopicEx(const char * topicName, IT3Filter* lpFilterInterface) = 0;

	/**
	* 获取订阅者所有已经订阅的主题以及过滤条件信息（以JSON串形式返回）
	* @note 返回对象非NULL时，需要调用者通过Release接口释放
	* @note JSON对象包含的字段
	- SubcribeIndex
	- IsBornTopic
	- TopicName
	- TopicNo
	- Filter(JSON对象)
	- Appdata
	- isFromNow
	- Status
	*/
	virtual IT3JsonStr * FUNCTION_CALL_MODE GetAllSubcribeInfo() = 0;

	/**
	* 获取当前消息中心的所有主题信息（以JSON串形式返回）
	* @note 返回对象非NULL时，需要调用者通过Release接口释放
	* @note JSON对象包含的字段
	* - TopicName
	* - TopicNo
	* - ReliableLevel
	* - IssuePriority
	* - MsgLifetime
	* - Status
	* - TickStrategy
	* - BusinessVerify
	* - Local
	* - FilterField1
	* - FilterField2
	* - FilterField3
	* - FilterField4
	* - FilterField5
	* - FilterField6
	* - FilterField7
	* - FilterField8
	* - FilterField9
	* - FilterField10
	* - FilterField11
	* - FilterField12
	* - FilterField13
	* - FilterField14
	* - FilterField15
	* - FilterField16
	* - SubscribeStr
	* - PublishStr
	*/
	virtual IT3JsonStr * FUNCTION_CALL_MODE GetTopic() = 0;

	/**
	* 取服务器地址
	* @param lpPort 输出的服务器端口，可以为NULL
	* @return 返回服务器地址
	*/
	virtual const char * FUNCTION_CALL_MODE GetServerAddress(int *lpPort) = 0;

	/**
	* 获取订阅会话状态
	* @return 0		 与消息中心连接断开
	1		 正在与消息中心建立连接
	2		 与消息中心连接已建立
	*/
	virtual int FUNCTION_CALL_MODE GetSessionStatus() = 0;
};

/**
* 发布接口
*/
class IT3Publisher : public IBase
{
public:
	/**
	* 发布接口
	* @param topicName 主题名字，不知道名字就传NULL
	* @param lpFilter 过滤条件，需要上层自己指定，否则默认没有过滤条件
	* @param lpData 具体的内容
	* @param nLength 内容长度
	* @param iTimeOut 超时时间
	* @param bAddTimeStamp 是否添加时间戳，配合单笔性能查找
	* @return 返回0表示成功，返回其他值，根据错误号获取错误信息.
	*/
	virtual int FUNCTION_CALL_MODE PubMsg(const char * topicName, IT3Filter* lpFilter, const void *lpData, int nLength, int iTimeOut = -1,
		bool bAddTimeStamp = false) = 0;

	/**
	* 返回当前主题的发布序号
	* @param topicName 主题名字
	* @return 返回0表示没有对应的主题，返回其他值表示成功
	*/
	virtual unsigned int FUNCTION_CALL_MODE GetMsgNoByTopicName(const char * topicName) = 0;

	/**
	* 取服务器地址
	* @param lpPort 输出的服务器端口，可以为NULL
	* @return 返回服务器地址
	*/
	virtual const char * FUNCTION_CALL_MODE GetServerAddress(int *lpPort) = 0;

	/**
	* 获取当前消息中心的所有主题信息（以JSON串形式返回）
	* @note 返回对象非NULL时，需要调用者通过Release接口释放
	* @note JSON对象包含的字段
	* - TopicName
	* - TopicNo
	* - ReliableLevel
	* - IssuePriority
	* - MsgLifetime
	* - Status
	* - TickStrategy
	* - BusinessVerify
	* - Local
	* - FilterField1
	* - FilterField2
	* - FilterField3
	* - FilterField4
	* - FilterField5
	* - FilterField6
	* - FilterField7
	* - FilterField8
	* - FilterField9
	* - FilterField10
	* - FilterField11
	* - FilterField12
	* - FilterField13
	* - FilterField14
	* - FilterField15
	* - FilterField16
	* - SubscribeStr
	* - PublishStr
	*/
	virtual IT3JsonStr * FUNCTION_CALL_MODE GetTopic() = 0;
	//20191218 shizj #186107 t3sdk订阅发布支持设置gsvp
	/**
	* 发布接口-支持设置GSVP
	* @param topicName 主题名字，不知道名字就传NULL
	* @param lpFilter 过滤条件，需要上层自己指定，否则默认没有过滤条件
	* @param lpData 具体的内容
	* @param nLength 内容长度
	* @param szService 服务名
	* @param iTimeOut 超时时间
	* @param bAddTimeStamp 是否添加时间戳，配合单笔性能查找
	* @param szGroup Group
	* @param szVersion Version
	* @param szPartition 分片号信息
	* @return 返回0表示成功，返回其他值，根据错误号获取错误信息.
	*/
	virtual int FUNCTION_CALL_MODE PubMsgEx(const char * topicName, IT3Filter* lpFilter, const void *lpData, int nLength,
		const char* szService, int iTimeOut = -1, bool bAddTimeStamp = false, const char* szGroup = NULL, const  char* szVersion = NULL, const  char* szPartition = NULL) = 0;
};
///连接对象 IT3Connection 需要的回调对象接口定义
/**
* 包括连接成功、连接断开、收到数据、应答到达等事件
*/
class IT3Callback : public IBase
{
public:

	virtual ~IT3Callback() {};
	/**
	* 套接字连接成功
	* @param lpConnection 发生该事件的连接对象
	*/
	virtual void FUNCTION_CALL_MODE OnConnect(IT3Connection *lpConnection) = 0;

	/**
	* 完成安全连接
	* @param lpConnection 发生该事件的连接对象
	*/
	virtual void FUNCTION_CALL_MODE OnSafeConnect(IT3Connection *lpConnection) = 0;

	/**
	* 完成注册
	* @param lpConnection 发生该事件的连接对象
	*/
	virtual void FUNCTION_CALL_MODE OnRegister(IT3Connection *lpConnection) = 0;

	/**
	* 连接被断开
	* @param lpConnection 发生该事件的连接对象
	*/
	virtual void FUNCTION_CALL_MODE OnClose(IT3Connection *lpConnection) = 0;

	/**
	* 收到数据通知，之后对此hSend调用Receive应该会成功（必须调用Receive，否则数据一直会被缓存而占用内存）
	* @param lpConnection 发生该事件的连接对象
	* @param hSend        发送句柄
	* @param lpData       数据指针
	* @param nLength      数据长度
	*/
	virtual void FUNCTION_CALL_MODE OnReceiveNotify(IT3Connection *lpConnection, int hSend, const void *lpData, int nLength) = 0;

	/**
	* 收到发送时指定了ReplyCallback选项的请求的应答或者是没有对应请求的数据
	* @param lpConnection 发生该事件的连接对象
	* @param hSend        发送句柄
	* @param lpData       数据指针
	* @param nLength      数据长度
	*/
	virtual void FUNCTION_CALL_MODE OnReceived(IT3Connection *lpConnection, int hSend, const void *lpData, int nLength) = 0;
};

///SDK连接对象接口
/**
* 包括连接、断开、发送、接收等
*/
class IT3Connection : public IBase
{
public:
	///连接状态，可组合
	enum ConnectionStatus
	{
		Disconnected = 0x0000, /**< 未连接 */
		Connecting = 0x0001, /**< socket正在连接 */
		Connected = 0x0002, /**< socket已连接 */
		SafeConnecting = 0x0004, /**< 正在建立安全连接 */
		SafeConnected = 0x0008, /**< 已建立安全连接 */
		Registering = 0x0010, /**< 正注册 */
		Registered = 0x0020, /**< 已注册 */
		Rejected = 0x0040  /**< 被拒绝，将被关闭 */
	};

	///发送选项（可组合，0表示同步发送，通过Receive取应答）
	enum SendFlags
	{
		ReplyCallback = 0x0001,   /**< 通过回调取应答 */
		MultiReply = 0x0002,   /**< 有多个应答，即可以针对一个hSend多次 Receive */
		ThroughLine = 0x0200,   /**< 不另行添加PacketID，以buffer自带的PacketID为此次发送的PacketID*/
		RecyBufByUser = 0x0400    /**< 设置为用户自己释放接收数据 */
	};

	///接收选项（可组合，0表示接收超时时，不删除包ID，仍可再次调用Receive方法来尝试接收）
	enum RecvFlags
	{
		JustRemoveHandle = 0x0001   /**< 当接收超时时，把packet_id删除（以后再收到，则会以异步的方式收到），
									 注意，此参数是在Receive方法中传递（如果需要的话） */
	};
	virtual ~IT3Connection() {};
	/**
	* 初始化连接对象
	* @param lpCallback 回调对象
	* @return 返回0表示成功，否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	* 如果应用不需要任何回调方法，则可向该方法传递NULL，而不必自定义回调类和对象
	*/
	virtual int FUNCTION_CALL_MODE Create(IT3Callback *lpCallback) = 0;

	/**
	* 生成密钥对
	* @param szPubKey 返回公钥
	* @param uKeyLen szPubKey指向内存大小
	* @return 返回0表示成功，否则表示失败，返回值表示实际需要的内存大小
	*/
	virtual unsigned int FUNCTION_CALL_MODE GeneraterKey(char * szPubKey, unsigned int uKeyLen) = 0;

	/**
	* 初始化连接对象
	* @param lpCallback 回调对象
	* @param lpCertData 二进制证书文件缓存
	* @param nLength    二进制证书文件长度
	* @param szPWD      证书密码
	* @return 返回0表示成功，否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	* 如果应用不需要任何回调方法，则可向该方法传递NULL，而不必自定义回调类和对象
	*/
	virtual int FUNCTION_CALL_MODE CreateByMemCert(IT3Callback *lpCallback, void * lpCertData, int nLength, const char * szPWD) = 0;

	/**
	* 启动连接
	* @param uiTimeout 超时时间，单位毫秒，0表示不等待（使用代理连接服务器时，该参数不起作用）
	* @return 返回0表示成功，否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	*/
	virtual int FUNCTION_CALL_MODE Connect(unsigned int uiTimeout) = 0;

	/**
	* 断开连接
	* @param bSafe 是否为安全停止，默认为非安全停止
	* @param uiTimeout 安全停止超时时间，单位为ms
	* @return 返回0表示成功，否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	*/
	virtual int FUNCTION_CALL_MODE Close(bool bSafe = false, unsigned int uiTimeout = 5000) = 0;
	/**
	* 发送数据
	* @param lpData  待发送数据指针
	* @param nLength 待发送数据长度，最大长度为16M - 1
	* @param uiFlag  发送选项,可组合，0表示同步发送,1表示异步发送，其他选项可参考SendFlags
	* @return 返回发送句柄（正数），否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	*/
	virtual int FUNCTION_CALL_MODE Send(const void *lpData, int nLength, unsigned int uiFlag) = 0;

	/**
	* 接收数据
	* @param hSend     发送句柄
	* @param lppData   收到数据指针的地址
	* @param lpnLength 收到数据长度的地址
	* @param uiTimeout 超时时间，单位毫秒，0表示不等待
	* @param uiFlag    接收选项，0表示接收超时后仍可继续调用Receive来接收，
	*                  JustRemoveHandle表示当接收超时时，把packet_id删除（以后再收到，则会以异步的方式收到）
	* @return 返回0表示成功，否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	*/
	virtual int FUNCTION_CALL_MODE Receive(int hSend, void **lppData, int *lpnLength, unsigned int uiTimeout, unsigned int uiFlag) = 0;

	/**主动回收同步模式的队列缓存
	*  @param lpData 同步receive时返回的数据指针
	*  @note: 主动回收模式下，该接口必须调用，否则存在内存泄露
	*/
	virtual void FUNCTION_CALL_MODE RecycleDataBuf(void *lpData) = 0;

	/**
	* 取服务器地址
	* @param lpPort 输出的服务器端口，可以为NULL
	* @return 返回服务器地址
	*/
	virtual const char * FUNCTION_CALL_MODE GetServerAddress(int *lpPort) = 0;

	/**
	* 重新设置服务器地址接口
	* @param szServers 新的服务器地址
	* @note  必须单线程调用
	*/
	virtual int FUNCTION_CALL_MODE SetServers(const char * szServers) = 0;

	/**
	* 取连接状态
	* @return 返回连接状态
	*/
	virtual int FUNCTION_CALL_MODE GetStatus() = 0;

	/**
	* 取服务器负载，使用者可以同时创建多个连接实例同时连接不同的服务器，根据完成连接的时间以及负载决定使用哪个服务器
	* @return 返回服务器负载（非负数），越大表示越繁忙，否则表示失败，通过调用GetErrorMsg可以获取详细错误信息
	*/
	virtual int FUNCTION_CALL_MODE GetServerLoad() = 0;

	/**
	* 获取ip地址和端口
	* @return 获取ip地址和端口，格式：ip地址+端口
	*/
	virtual const char* FUNCTION_CALL_MODE GetRealAddress() = 0;

	/**
	* 获取ip地址和端口
	* @return 获取ip地址和端口，格式：ip地址+端口
	*/
	virtual const char* FUNCTION_CALL_MODE GetSelfAddress() = 0;

	/**
	* 获取MAC地址
	* @return MAC的地址字符串格式，类似“D067E5556D83”,中间没有分隔符
	*/
	virtual const char* FUNCTION_CALL_MODE GetSelfMac() = 0;

	/**
	* 获取所连接的服务器的节点名
	* @return 节点名
	*/
	virtual const char * FUNCTION_CALL_MODE GetServerNodeName() = 0;

	/**
	* 唯一序号前缀，最大支持255字节
	* @param lpPrefix
	*/
	virtual void FUNCTION_CALL_MODE SetUniquePrefix(const char* lpPrefix) = 0;

	/**
	* 取连接错误号，当连接无法与服务端完成注册时，调用该方法可获取错误号，然后用该错误号调用GetErrorMsg
	* 可获取可读的错误信息
	* @return 返回连接错误号
	*/
	virtual int FUNCTION_CALL_MODE GetConnectError() = 0;

	/**
	* 取错误码对应的错误信息，目前支持简体中文和英文，支持其他语言可以通过连接对象配置errormsg
	* @param nErrorCode 错误码
	* @return 返回错误信息
	*/
	virtual const char * FUNCTION_CALL_MODE GetErrorMsg(int nErrorCode) = 0;
	//20190609 majc #236959 t3sdk增加接口获取分片列表
	/**
	* 获取某服务某功能号的所有分片信息
	* @param szService 服务名
	* @param iTimeOut 超时时间
	* @param szResultBuf 存放结果的buffer
	* @param iRetLen buffer的长度，同时返回结构的实际长度，当szResultBuf为NULL或小于结果长度时，返回实际长度；
	* @param iFlag 是否需要完整分片信息，0只返回分片列表信息，1返回完整分片内容信息
	* @return 成功返回0,否则失败
	*/
	virtual int FUNCTION_CALL_MODE GetShardingCollectInfo(const char * szService, int iTimeOut, char * szResultBuf, int& iRetLen, const char * szGroup = NULL, const char* szVersion = NULL, int iFlag = 0) = 0;
	///20191028 huxb #161459 支持消息中心发布订阅
	/**
	* 获取当前消息中心的所有主题信息（以JSON串形式返回）
	* @param byForce 是否强制从后台获取
	* @param iTimeOut 超时时间
	* @note 返回对象非NULL时，需要调用者通过Release接口释放
	* @note JSON对象包含的字段
	* - TopicName
	* - TopicNo
	* - ReliableLevel
	* - IssuePriority
	* - MsgLifetime
	* - Status
	* - TickStrategy
	* - BusinessVerify
	* - Local
	* - FilterField1
	* - FilterField2
	* - FilterField3
	* - FilterField4
	* - FilterField5
	* - FilterField6
	* - FilterField7
	* - FilterField8
	* - FilterField9
	* - FilterField10
	* - FilterField11
	* - FilterField12
	* - FilterField13
	* - FilterField14
	* - FilterField15
	* - FilterField16
	* - SubscribeStr
	* - PublishStr
	*/
	virtual IT3JsonStr * FUNCTION_CALL_MODE GetTopic(int iTimeOut, SUB_ROUTER_INFO * lpRouteInfo) = 0;
	/**获取最近一次错误信息
	*/
	virtual const char* FUNCTION_CALL_MODE GetMCLastError() = 0;
	/**
	* 获取订阅者
	* @param lpCallback 订阅者回调
	* @param SubScribeName 订阅者名称
	* @param lpRouteInfo 路由信息
	* @param iTimeOut 订阅超时时间
	* @param bCluster 是否集群订阅
	* @return 成功返回订阅者实例，失败通过GetMCLastError获取错误信息
	*/
	virtual IT3Subscriber* FUNCTION_CALL_MODE NewSubscriber(IT3SubCallback *lpCallback, const char * SubScribeName, SUB_ROUTER_INFO * lpRouteInfo, int iTimeOut, bool bCluster = false) = 0;
	/**
	* 获取发布者
	* @param PublishName 发布者业务名
	* @param msgCount 本地缓存消息的个数
	* @param iTimeOut 初始化超时时间
	* @param bResetNo 是否重置发布序号
	* @return 成功返回发布者实例，失败通过GetMCLastError获取错误信息
	*/
	virtual IT3Publisher* FUNCTION_CALL_MODE NewPublisher(const char * PublishName, int msgCount, int iTimeOut, bool bResetNo = false) = 0;
	//20191218 shizj #186107 t3sdk订阅发布支持设置gsvp	
	/**
	* 获取当前消息中心的所有主题信息（以JSON串形式返回）
	* @param byForce 是否强制从后台获取
	* @param iTimeOut 超时时间
	* @note 返回对象非NULL时，需要调用者通过Release接口释放
	* @note JSON对象包含的字段
	* - TopicName
	* - TopicNo
	* - ReliableLevel
	* - IssuePriority
	* - MsgLifetime
	* - Status
	* - TickStrategy
	* - BusinessVerify
	* - Local
	* - FilterField1
	* - FilterField2
	* - FilterField3
	* - FilterField4
	* - FilterField5
	* - FilterField6
	* - FilterField7
	* - FilterField8
	* - FilterField9
	* - FilterField10
	* - FilterField11
	* - FilterField12
	* - FilterField13
	* - FilterField14
	* - FilterField15
	* - FilterField16
	* - SubscribeStr
	* - PublishStr
	*/
	virtual IT3JsonStr * FUNCTION_CALL_MODE GetTopicEx(int iTimeOut, const char* szService, const char* szGroup = NULL,
		const  char* szVersion = NULL, const  char* szPartition = NULL) = 0;
	/**
	* 获取订阅者-支持设置GSVP
	* @param lpCallback 订阅者回调
	* @param SubScribeName 订阅者名称
	* @param iTimeOut 订阅超时时间
	* @param szService 服务名
	* @param bCluster 是否集群订阅
	* @param szGroup Group
	* @param szVersion Version
	* @param szPartition 分片号信息
	* @return 成功返回订阅者实例，失败通过GetMCLastError获取错误信息
	*/
	virtual IT3Subscriber* FUNCTION_CALL_MODE NewSubscriberEx(IT3SubCallback *lpCallback, const char * SubScribeName, int iTimeOut,
		const char* szService, bool bCluster = false, const char* szGroup = NULL, const  char* szVersion = NULL, const  char* szPartition = NULL) = 0;
	/**
	* 获取发布者-支持设置GSVP
	* @param PublishName 发布者业务名
	* @param msgCount 本地缓存消息的个数
	* @param iTimeOut 初始化超时时间
	* @param szService 服务名
	* @param bResetNo 是否重置发布序号
	* @param szGroup Group
	* @param szVersion Version
	* @param szPartition 分片号信息
	* @return 成功返回发布者实例，失败通过GetMCLastError获取错误信息
	*/
	virtual IT3Publisher* FUNCTION_CALL_MODE NewPublisherEx(const char * PublishName, int msgCount, int iTimeOut, const char* szService,
		bool bResetNo = false, const char* szGroup = NULL, const  char* szVersion = NULL, const  char* szPartition = NULL) = 0;
};
extern "C"
{
	/**
	* 获取版本信息
	* @return 返回值version 1.0.0.1 __DATE__ __TIME__
	*/
	const char* FUNCTION_CALL_MODE GetT3sdkVersionInfo();
	/**
	* 获取配置对象
	* @return 失败返回NULL，否则成功
	*/
	IT3Config * FUNCTION_CALL_MODE NewConfig();
	/**
	* 获取连接对象
	* @param lpConfig 配置对象
	* @return 失败返回NULL，否则成功
	*/
	IT3Connection * FUNCTION_CALL_MODE NewConnection(IT3Config *lpConfig);
	/**
	* 获取消息对象
	* @param nCompressID 是否压缩
	* @return 失败返回NULL，否则成功
	*/
	IT3Message* FUNCTION_CALL_MODE NewMessage(MessageType type = HSRequest, const char * szFunction = NULL, int nCompressID = 1);
	/**
	* 初始化加载sdk
	* @return 成功返回0，否则失败
	*/
	int FUNCTION_CALL_MODE T3sdkInit();
	/**
	* 卸载sdk
	* @return 成功返回0，否则失败
	*/
	int FUNCTION_CALL_MODE T3sdkUnInit();
	///20191023 huxb #173033 提供柜台加密接口
	/**
	* 对称加密
	* @param auth_id 加密盐值
	* @param auth_type 盐值业务类型
	* @param encode_type 加密算法，0表示AES， 1表示SM4
	* @param plainText 明文
	* @param pOut 密文输出缓存(输出缓存大小必须是明文长度(明文长度需要按照16字节向上取整)的2倍)
	* @return 0表示成功，其他表示失败。其中，-2表示加密算法非法
	*/
	int FUNCTION_CALL_MODE Encode3(const char * auth_id, unsigned char auth_type, unsigned char encode_type, const char * plain_text, char * pOut);
	///20191028 huxb #161459 支持消息中心发布订阅
	/**
	* 获取过滤条件对象
	* @return 失败返回NULL，否则成功
	*/
	IT3Filter * FUNCTION_CALL_MODE NewFilter();
	/**
	* 获取订阅属性对象
	* @return 失败返回NULL，否则成功
	*/
	IT3SubParam * FUNCTION_CALL_MODE NewSubscribeParam();
	/**
	* 获取Json串对象
	* @return 失败返回NULL，否则成功
	*/
	IT3JsonStr * FUNCTION_CALL_MODE NewJsonStr();
}
END_T3SDK_NAMESPACE

#endif